package com.uu.plugin;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.Configuration;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.PreparedStatement;
import java.util.*;

/**
 * 对mybatis入参进行拦截加密
 * <p>
 *
 * @author richinfo
 * @see DefaultParameterHandler#setParameters(PreparedStatement)
 */
@Intercepts(@Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}))
public class MOAEncryptInterceptor implements Interceptor {

    private Map<Object, Field[]> cache = new HashMap<>();

    @Override
    public Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println("MOAEncryptInterceptor intercept:" + invocation);
        Object target = invocation.getTarget();
        if (target instanceof DefaultParameterHandler) {
            DefaultParameterHandler handler = (DefaultParameterHandler) target;
            this.handleParam(handler);
        }
        return invocation.proceed();
    }

    private void handleParam(DefaultParameterHandler handler) {
        BoundSql boundSql = (BoundSql) ObjectUtil.getValue(handler, "boundSql");
        System.out.println("boundSql:" + boundSql);

        // sql 获得类型
        MappedStatement mappedStatement = (MappedStatement) ObjectUtil.getValue(handler, "mappedStatement");
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        if (SqlCommandType.INSERT == sqlCommandType) {

        }

        // sql 参数
        Object parameterObject = ObjectUtil.getValue(handler, "parameterObject");
        System.out.println("parameterObject:" + parameterObject);
        Field[] fields = getAllFields(parameterObject);
        for (Field f : fields) {
            boolean annotationPresent = f.isAnnotationPresent(M.class);
            System.out.println("annotationPresent:" + annotationPresent);
        }

        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if (!ObjectUtil.isEmpty(parameterMappings)) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    String propertyName = parameterMapping.getProperty();

                    // 判断参数属性是否有注解
                    Class<?> javaType = parameterMapping.getJavaType();
                    if (String.class.equals(javaType)) {
//                      ObjectUtil.setValue(parameterObject, propertyName, "xxoo");
                    }
                }
            }
        }
    }

    /**
     * 获得对象的属性
     *
     * @param object 原对象
     * @return 对象的属性数组
     */
    public static Field[] getAllFields(Object object) {
        Class clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            if (Objects.class.equals(clazz)) {
                break;
            }
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof ParameterHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {
    }
}